from sqlalchemy import create_engine
from model import Symbol, DailyData
from sqlalchemy.orm import sessionmaker

import os
import sys
import json
import urllib2
import datetime


# Amount of days to use while calculating the SMA
SMA_LENGTH = 2

# Amount of days to use while calculating the STF
STF_LENGTH = 2

# Amount of days to determine if some value is Raising or Falling
TENDENCY_DAYS=3


class FactsGenerator():

    def __init__(self, factsDir, database):

        self._database = "sqlite:///%s" % database

        self._factsDir=factsDir
        self._engine = create_engine(self._database, echo=False)
        Session = sessionmaker(bind=self._engine)
        self._session = Session()

    def _calculateSMA(self, symbol):


        # TODO sort by date
        dailyDataList =  self._session.query(DailyData).filter_by(symbol_name=symbol.name).all()

        print "*"*100
        print symbol

        nDailyData =  len(dailyDataList)
        if nDailyData < SMA_LENGTH:
            print "\tSkipping this symbol, not enough data"
            return None
            

        smas = {}
        n = 0

        for dailyData in dailyDataList:


            if dailyData.buyPrice <= 0:
                print "\tSkipping this symbol, buyPrice <= 0"
                return None

            if dailyData.sellPrice <=0:
                print "\tSkipping this symbol, sellPrice <= 0"
                return None

            price = (dailyData.buyPrice + dailyData.sellPrice)/2


            stop = n-SMA_LENGTH
            if stop < -1:
                stop = -1

            for i in range(n, stop, -1):

                if not i in smas.keys():
                    smas[i] = price
                else:
                    smas[i] = smas[i] + price

                if (nDailyData - i) < SMA_LENGTH:
                    #print "\t Skipping, not enough historic data"
                    continue
                #print "smas[%d] = smas[%d] + %d" % (i, i, price)

            n = n+1

        for key in smas.keys():
            smas[key] = smas[key]/SMA_LENGTH
            print "\tSMA: %g" % smas[key] 

        return smas


    def _SMAIsRisingFalling(self, smas):

        #print "#"*80
        #print "CALCULATING SMA RAISE/FALL"
        
        isRaising = True
        isFalling = True

        keys = smas.keys()[:TENDENCY_DAYS]
        keys.sort(reverse=True)

        isFirst = True
        for key in keys:

            #print key
            #print smas[key]

            if isFirst:
                isFirst=False
                continue

            if ((smas[key+1] < smas[key]) and isRaising):
                isRaising = True
            else:
                isRaising = False
            
            if ((smas[key+1] > smas[key]) and isFalling):
                isFalling = True
            else:
                isFalling = False
            
        #print "#"*80
        return (isRaising, isFalling) 


    def _priceIsRisingFalling(self, symbol):

        #print "#"*80
        #print "CALCULATING Price RAISE/FALL"


        prices = {}

        #TODO sort by date
        n=0
        dailyDataList =  self._session.query(DailyData).filter_by(symbol_name=symbol.name).all()
        for dailyData in dailyDataList:
            if dailyData.buyPrice <= 0:
                print "\tSkipping this symbol, buyPrice <= 0"
                return None

            if dailyData.sellPrice <=0:
                print "\tSkipping this symbol, sellPrice <= 0"
                return None

            price = (dailyData.buyPrice + dailyData.sellPrice)/2
            prices[n] = price
            n = n+1


        isRaising = True
        isFalling = True


        keys = prices.keys()[:TENDENCY_DAYS]
        keys.sort(reverse=True)

        isFirst = True
        for key in keys:

            #print key
            #print prices[key]

            if isFirst:
                isFirst=False
                continue

            if ((prices[key+1] < prices[key]) and isRaising):
                isRaising = True
            else:
                isRaising = False
            
            if ((prices[key+1] > prices[key]) and isFalling):
                isFalling = True
            else:
                isFalling = False
            
        #print "#"*80
        return (isRaising, isFalling) 



    def SMAIntersectsPrice(self, smas, symbol):
        prices = {}

        #TODO sort by date
        n=0
        dailyDataList =  self._session.query(DailyData).filter_by(symbol_name=symbol.name).all()
        for dailyData in dailyDataList:
            if dailyData.buyPrice <= 0:
                print "\tSkipping this symbol, buyPrice <= 0"
                return None

            if dailyData.sellPrice <=0:
                print "\tSkipping this symbol, sellPrice <= 0"
                return None

            price = (dailyData.buyPrice + dailyData.sellPrice)/2
            prices[n] = price
            n = n+1

        if len(smas.keys()) < TENDENCY_DAYS:
            print "Skipping this symbol, not enough sma data"
            return none

        if len(prices.keys()) < TENDENCY_DAYS:
            print "Skipping this symbol, not enough price data"
            return none

        print "pri %g \t %g" % (prices[0], prices[TENDENCY_DAYS-1])
        print "sma %g \t %g" % (smas[0], smas[TENDENCY_DAYS-1])

        if ((smas[0] >= prices[0]) and (smas[TENDENCY_DAYS-1] <= prices[TENDENCY_DAYS-1])):
            return True

        if ((smas[0] <= prices[0]) and (smas[TENDENCY_DAYS-1] >= prices[TENDENCY_DAYS-1])):
            return True

        return False


    #Calculate Stochastic Fast
    def _calculateSTF(self, symbol):


        # TODO sort by date
        dailyDataList =  self._session.query(DailyData).filter_by(symbol_name=symbol.name).all()

        print "*"*100
        print symbol

        nDailyData =  len(dailyDataList)
        if nDailyData < STF_LENGTH:
            print "\tSkipping this symbol, not enough data"
            return None
            

        first = True
        high = 0
        low  = 0
        current = 0

        for dailyData in dailyDataList:


            if dailyData.buyPrice <= 0:
                print "\tSkipping this symbol, buyPrice <= 0"
                return None

            if dailyData.sellPrice <=0:
                print "\tSkipping this symbol, sellPrice <= 0"
                return None

            price = (dailyData.buyPrice + dailyData.sellPrice)/2

            if first:
                first=False
                high = price
                low = price
                current = price
            else:
                if price > high:
                    high = price
                if price < low:
                    low = price


        K_Percent = ((current - low)/(high-low))*100

        return K_Percent

    def _calculateSTFIndicators(self, symbol):
        stf = self._calculateSTF(symbol)
        print "\t Stochastic Fast is %g" % stf

        overbought = (stf>=80)
        oversell   = (stf<=20)
        return (oversell, overbought)


    def run(self):
   
  
        symbols = self._session.query(Symbol).all()
        for symbol in symbols:

            if len(symbol.name) == 0:
                continue

            fname = os.path.join(self._factsDir, "%s.xml" % symbol.name)


            smas = self._calculateSMA(symbol)
            if smas == None:
                continue

            fd = open(fname, "a")
            fd.write("<facts>\n")

            smaIsRaising, smaIsFalling = self._SMAIsRisingFalling(smas)
            print "\tSMA is Raising : %s" % smaIsRaising
            print "\tSMA is Falling : %s" % smaIsFalling
           
            priceIsRaising, priceIsFalling = self._priceIsRisingFalling(symbol)
            print "\tPrice is Raising : %s" % priceIsRaising
            print "\tPrice is Falling : %s" % priceIsFalling

            smaIntersectsPrice = self.SMAIntersectsPrice(smas, symbol)
            print "\tSMA intersects Price : %s" % smaIntersectsPrice

            
            stfOversell, stfOverbought = self._calculateSTFIndicators(symbol)


            fd.write("\t<symbol name=\"%s\">\n" % symbol.name)

            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("SMA_IS_RAISING", smaIsRaising))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("SMA_IS_FALLING", smaIsFalling))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("PRICE_IS_RAISING", priceIsRaising))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("PRICE_IS_FALLING", priceIsFalling))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("SMA_INTERSECTS_PRICE", smaIntersectsPrice))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("SMA_INTERSECTS_PRICE", smaIntersectsPrice))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("STF_OVERSELL", stfOversell))
            fd.write("\t\t<fact name=\"%s\" value=\"%s\"/>\n" % ("STF_OVERBOUGHT", stfOverbought))


            
            fd.write("\t</symbol>\n")
            #if smaIntersectsPrice and smaIsFalling and priceIsRaising:
            #    print "%"*100

            #if smaIntersectsPrice and smaIsRaising and priceIsFalling:
            #    print "%"*100
            fd.write("</facts>\n")
            fd.close()

if __name__ == "__main__":

    if len(sys.argv) < 3:
        sys.exit('Usage: %s facts-directory database' % sys.argv[0])

    fg = FactsGenerator(sys.argv[1], sys.argv[2])
    fg.run()

   #print json.dumps(data, sort_keys=True, indent=4, separators=(',', ': '))
